#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define WIDTH  640
#define HEIGHT 480
#define ELLIPSE_A 	WIDTH / 16
#define ELLIPSE_B 	HEIGHT / 20
#ifndef M_PI
#define M_PI 3.1415926
#endif

double boxMuller();
double gaussianRandom(double mu, double sigma);
void drawEllipse(SDL_Renderer *renderer,
		int center_x, int center_y, int a, int b);
void drawFilledEllipse(SDL_Renderer* renderer,
		int center_x, int center_y, int a, int b);

int main()
{
	srand((unsigned int) time(NULL));

	int quit;
	int x;
	SDL_Window *window = NULL;
	SDL_Renderer *renderer = NULL;
	SDL_Event e;

	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
		fprintf(stderr, "SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
		exit(-1);
	}

	window = SDL_CreateWindow("Gauss Distribution",
			SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
			WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
	if (!window) {
		fprintf(stderr, "Window could not be created! SDL_Error: %s\n", SDL_GetError());
		SDL_Quit();
		exit(-1);
	}

	renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
	if (!renderer) {
		fprintf(stderr, "Renderer could not be created! SDL_Error: %s\n", SDL_GetError());
		SDL_DestroyWindow(window);
		SDL_Quit();
		exit(-1);
	}

	// Set background color
	SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
	SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
	SDL_RenderClear(renderer);

	// Set draw color
	SDL_SetRenderDrawColor(renderer, 169, 169, 169, 10);

	quit = 0;
	while (!quit) {
		while (SDL_PollEvent(&e) != 0) {
			if (e.type == SDL_QUIT) {
				quit = 1; 
				break;
			}
		}
		x = (int) gaussianRandom((double) WIDTH * 2 / 5, 40);
		SDL_Rect rect = { x, HEIGHT/ 2, ELLIPSE_A, ELLIPSE_B };
		SDL_RenderFillRect(renderer, &rect);
		// drawFilledEllipse(renderer, x, HEIGHT / 2, ELLIPSE_A, ELLIPSE_B);

		SDL_RenderPresent(renderer);
		SDL_Delay(16);
	}

	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	SDL_Quit();

	exit(0);
}

double boxMuller()
{
	double u1, u2, z0;

	u1 = (double) rand() / RAND_MAX;
	u2 = (double) rand() / RAND_MAX;
	z0 = sqrt(-2 * log(u1)) * cos(2 * M_PI * u2);

	return z0;
}

double gaussianRandom(double mu, double sigma)
{
	return mu + sigma * boxMuller();
}

void drawEllipse(SDL_Renderer *renderer,
		int center_x, int center_y, int a, int b)
{
	const int num_samples = 360;
	float angle;
	int x, y;

	for (int i = 0; i < num_samples; i++) {
		angle = i * 2.0f * M_PI / num_samples;
		x = center_x + (int) (a * cos(angle));
		y = center_y + (int) (b * sin(angle));

		SDL_RenderDrawPoint(renderer, x, y);
	}

}

void drawFilledEllipse(SDL_Renderer* renderer, int center_x, int center_y, int a, int b) 
{
    for (int y = -b; y <= b; ++y) {
        for (int x = -a; x <= a; ++x) {
            if ((x * x) / (float)(a * a) + (y * y) / (float)(b * b) <= 1.0f) {
                SDL_RenderDrawPoint(renderer, center_x + x, center_y + y);
            }
        }
    }
}
